home *** CD-ROM | disk | FTP | other *** search
- Path: mail2news.demon.co.uk!genesis.demon.co.uk
- From: Lawrence Kirby <fred@genesis.demon.co.uk>
- Newsgroups: comp.lang.c
- Subject: Re: malloc question
- Date: Tue, 12 Mar 96 19:31:36 GMT
- Organization: none
- Message-ID: <826659096snz@genesis.demon.co.uk>
- References: <4htonk$350@news.hklink.net> <4i492m$9jl@news1.warwick.net>
- Reply-To: fred@genesis.demon.co.uk
- X-NNTP-Posting-Host: genesis.demon.co.uk
- X-Newsreader: Demon Internet Simple News v1.27
- X-Mail2News-Path: genesis.demon.co.uk
-
- In article <4i492m$9jl@news1.warwick.net>
- acorn@warwick.net "Peter Kohlberger" writes:
-
- >alex@station.net (Alex Chu) wrote:
- >>Hi everybody,
- >
- >>I have a question for the following snip C program.
- >
- >>typedef struct item {
- >> int val;
- >> struct item *next;
- >>} ITEM, *PITEM;
- >
- >>main()
- >>{
- >> PITEM head, current;
- >> head=(PITEM) malloc(sizeof(ITEM));
- >> ^^^^^^^
- >> head->val=1;
- >>}
-
- >Without the cast, you can not convert *void into *ITEM;
-
- You can if you are using the C language - the compiler must convert
- any pointer (other than a pointer to a function) to and from a pointer to
- void implicitly where the context demands it (almost, there are rules about
- const/volatile qualifiers that have to be met).
-
- with the cast,
- >you are allowed to do the conversion. If the conversion is allowed in
- >one manner, why is it not allowed in the other manner?
- >
- >The answer is (mostly) so that the compiler can catch your errors.
- >While a pointer to void can be converted to a pointer to any type of
- >object, it's desirable to ensure that the conversion is the actual
- >intent of the programmer.
-
- What you describe here is true for pointers in general (and notably for
- char * which took on the role of 'generic' pointer before the introduction
- of void *) but not true for void * in particular.
-
- ...
-
- >If the above call to malloc() without a cast was allowed, head2 would
- >be allocated 6 bytes when it needs 46 bytes (in my environment).
- >Requiring the cast changes the code to:
- >
- > head2 =(PITEM1)malloc(sizeof(ITEM1));
-
- All this guarantees is that the type of the cast matches the type of the
- pointer being assigned to. Since the cast is otherwise unconstrained this
- doesn't help you much. For instance the compiler wouls quite happily accept:
-
- head2 =(PITEM2)malloc(sizeof(ITEM1));
-
- You could try to improve on this by using a macro e.g.
-
- #define malloc2(nelems, type) ((type *)malloc((nelems) * sizeof(type))))
-
- Unfortunately the preprocessor can't handle general type derivations and this
- fails if you pass the type as, say, char [8]. Another approach would be to:
-
- #define malloc3(ptr, nelems) ((ptr) = malloc((nelems) * sizeof *(ptr))
-
- which works because a cast is not necessary. The main drawback here is that
- it looks like a function call in usage but doesn't act like one (i.e. it
- modifies an argument). If that wasn't acceptable then you could use:
-
- #define malloc4(ptr, nelems) (*(ptr) = malloc((nelems) * sizeof **(ptr))
-
- and write, say,
-
- int *ip;
-
- if (malloc4(&ip, arraysize) == NULL) { /*...*/ }
-
- Quite neat but it could throw you in code you weren't familiar with. It would
- be good as part of the standard however.
-
- --
- -----------------------------------------
- Lawrence Kirby | fred@genesis.demon.co.uk
- Wilts, England | 70734.126@compuserve.com
- -----------------------------------------
-